import json
import math
import os
import time
import traceback
from datetime import datetime
from os import path
from typing import List

import fitz
import requests
from sqlalchemy import and_

from apps.db import db
from apps.logger_config import logger
from apps.model import BankSideInfo, BankSideExtendInfo, HouseConfirm, DiyaPerson
from apps.model.house_approve import HouseApprove
from apps.seleuinms.process import Job
from apps.seleuinms.requests import HouseRequest
from apps.seleuinms.utils.request_utils import parse_response
from apps.utils import get_file_name, curtime, model_dict_clear

file_basepath = path.join(path.dirname(path.abspath(__file__)), '../../../static/chanquan')


def query_approve_data(query: dict, cookies: dict):
    url = "http://bdcserver:8066/estateplat-bank/query/bank/queryZmh"
    data = {
        "bdcqzh": "",
        "bdcqzmh": "",
        "dyr": query.get('dyr'),
        "zl": query.get('zl'),
        "dyrzjhm": query.get('dyrzjhm'),
        "qlr": "allsub",
        "proids": [],
        "iscf": "no",
        "qlzt": "",
        "isydy": query.get('isydy', 'no'),
        "cxmd": "",
        "djcjkasj": query.get('djcjkasj'),
        "djcjjssj": query.get('djcjjssj')
    }
    params = {
        "_search": "false",
        "nd": math.ceil(datetime.now().timestamp() * 1000),
        "rows": "20",
        "page": "1",
        "sidx": "OrderDate",
        "sord": "asc",
        "json": json.dumps(data, ensure_ascii=False),
    }
    res = requests.get(url, params=params, cookies=cookies)
    return parse_response(res)


def pyMuPDF_fitz(pdfPath, imagePath):
    pdf_doc = fitz.open(pdfPath)
    page = pdf_doc[0]
    rotate = int(0)
    # 每个尺寸的缩放系数为1.3，这将为我们生成分辨率提高2.6的图像。
    # 此处若是不做设置，默认图片大小为：792X612, dpi=96
    zoom_x = 2  # (1.33333333-->1056x816)   (2-->1584x1224)
    zoom_y = 2
    mat = fitz.Matrix(zoom_x, zoom_y).preRotate(rotate)
    pix = page.getPixmap(matrix=mat, alpha=False)

    pix.writePNG(imagePath)  # 将图片写入指定的文件夹内


def frompic2pdf(img_path, pdf_path):
    # 打开空文档
    doc = fitz.open()
    # 打开指定图片
    imgdoc = fitz.open(img_path)
    # 使用图片创建单页的PDF
    pdfbytes = imgdoc.convertToPDF()
    imgpdf = fitz.open("pdf", pdfbytes)
    # 将当前页写入文档
    doc.insertPDF(imgpdf)
    # 保存为指定名称的PDF文件
    doc.save(pdf_path)
    # 关闭
    doc.close()


def combine_pdf(pdf_path: str, pdf_name: str):
    file_name = pdf_name.replace('.pdf', '')
    image_path = path.join(pdf_path, file_name + '.png')
    pdf_file_path = path.join(pdf_path, pdf_name)
    pyMuPDF_fitz(pdf_file_path, image_path)

    # 删除原来的pdf文件
    os.remove(pdf_file_path)

    # 将图片转化为新的pdf文件
    frompic2pdf(image_path, pdf_file_path)

    os.remove(image_path)


class HouseThread(Job):
    __job_name__ = '3.0回填系统'

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.cookies = {}

    def login(self):
        # 不动产系统登录
        self.cookies = HouseRequest.cookie_dict
        if not self.cookies:
            instance = HouseRequest()
            instance.login()
            self.cookies = HouseRequest.cookie_dict

    def after_get_qz(self, rows: List, extend: BankSideExtendInfo, item):
        """获取权证后的处理"""
        real_row = None
        if len(rows) == 1:
            real_row = rows[0]
        else:
            # 当数据为多条的时候，需要比较
            url = 'http://bdcserver:8066/estateplat-bank/query/bank/zlList'
            data = {
                'json': json.dumps({"proids": [row.get('PROID') for row in rows]})
            }
            zllist = requests.post(url, data=data, cookies=self.cookies)
            zllist = parse_response(zllist)

            for zl in zllist:
                ZL = zl.get('ZL')
                if ZL in extend.house_located or extend.house_located in ZL or extend.house_located[-7:] == ZL[-7:]:
                    # 匹配上了
                    PROID = zl.get('PROID')
                    for row in rows:
                        if row.get('PROID') == PROID:
                            real_row = row
                            break
                    break

        if real_row is None:
            # 没有找到相关数据
            logger.error('未找到该客户 %s 的权证信息, 他的坐落为 %s , 合同号为 %s', item.get('custom_name'), extend.house_located,
                         extend.contract_no)

        from apps.app import app

        logger.info('已找到 %s 的权证信息 %s', item.get('custom_name'), real_row.get('BDCDJZMH'))
        """
        BDBZZQSE: 490000
        BDBZZQSEYUAN: 4900000000
        BDCDJZMH: "苏(2021)盐城市不动产证明第0003869号"
        BDCDYBH: ""
        BDCDYH: "320902014003GB00027F00040037"
        BDCDYID: "4CB91857EANQN6M3"
        BJSJ: "2021-01-12 15:13:58"
        DJSJ: "2021-01-12 11:42:48"
        DWDM: "3209"
        DYJSRQ: "2041-01-07"
        DYKSRQ: "2021-01-07"
        DYSW: ""
        LCMC: "存量房转移、抵押组合"
        PROID: "51CA0831QMNQN981"
        ROWNUM_: 1
        XMLY: "bdc"
        YCQQLID: "51CA08325SNQN98V"
        YCQZH: "苏(2021)盐城市不动产权第0003286号"
        YSLSH: ""
        """
        qz_type = '抵押登记证明'
        # 只有一手类贷款为预告抵押登记证明
        if '个人一手' in item.get('baseWork_flow_name') and item.get('state') == 'waitApprove':
            qz_type = '预告抵押登记证明'
        has_end = '0'
        if real_row.get('DYJSRQ') is not None:
            has_end = '1'
        # 下载电子证书
        url = "http://bdcserver:8066/estateplat-bank/query/bank/printPdfZm?proid=" + real_row.get('PROID')
        logger.info('开始下载 %s 的证书附件 url: %s', item.get('custom_name'), url)
        f = requests.get(url, cookies=self.cookies)

        approve = {
            'extend_id': extend.id,
            'qz_type': qz_type,
            'qz_no': real_row.get('BDCDJZMH'),
            'dj_apartment_type': '房产管理部门',
            'dj_apartment': '盐城市自然资源和规划局',
            'dj_amt': real_row.get('BDBZZQSE'),
            'dj_start_date': real_row.get('DYKSRQ'),
            'dj_end_date': real_row.get('DYJSRQ'),
            'has_end': has_end,
        }
        # pdf下载完成后进行转换，合并图层
        try:
            if f.content.__len__() == 0:
                # 未找到长产证
                logger.error('不动产附件转化失败！ msg: %s', '未找到不动产权证书附件')
                raise Exception('未找到不动产权证书附件!')
                # with app.app_context():
                #     info = BankSideInfo.get(item.get('id'))
                #     info.state = 'error'
                #     info.error_msg = '未找到不动产权证书附件'
                #     info.save()
                #     HouseApprove(**approve).save(commit=True)
                # return
            filename = get_file_name(f.headers)
            approve['file'] = filename
            with open(path.join(file_basepath, filename), 'wb') as fo:
                fo.write(f.content)
            combine_pdf(file_basepath, filename)
        except Exception as e:
            logger.error('不动产附件转化失败！ msg: %s', str(e))
            return
        with app.app_context():
            if item.get('state') == 'confirmed':
                info = BankSideInfo.get(item.get('id'))
                info.create_time = curtime()
                info.save()
                HouseConfirm(**approve).save(commit=True)
                return
            info = BankSideInfo.get(item.get('id'))
            info.state = 'approved'
            info.create_time = curtime()
            info.save()
            HouseApprove(**approve).save(commit=True)

    def process(self, item: dict):
        from apps.app import app
        with app.app_context():
            extend_list: List[BankSideExtendInfo] = BankSideExtendInfo.filter_by(contract_id=item.get('id')).all()
        for extend in extend_list:
            if extend is None or extend.house_located is None:
                logger.error('未找到 %s 的拓展信息， 请检查', item.get('custom_name'))
                return

            # 根据抵押人信息查询办证信息
            with app.app_context():
                diys = DiyaPerson.filter_by(extend_id=extend.id).all()
            for d in diys:
                query = {
                    'dyr': d.name,
                    'dyrzjhm': d.cert_no,
                    'djcjkasj': extend.contract_start_date,
                    'djcjjssj': extend.contract_end_date,
                }

                # 如果为一手房预抵押
                if '个人一手' in item.get('baseWork_flow_name') and item.get('state') == 'waitApprove':
                    query['isydy'] = 'yes'
                res = query_approve_data(query, self.cookies)
                if res is not None and res.get('total') > 0:
                    rows = res.get('rows')
                else:
                    rows = []
                if rows is not None and len(rows) > 0:
                    self.after_get_qz(rows, extend, item)
                    break

    def executor(self, uid: str = None):
        try:
            if not self.cookies:
                self.login()
            from apps.app import app
            with app.app_context():
                # 查询当前系统中所有等待审核的数据，包含二手房抵押申请，一手房预告抵押申请
                data = BankSideInfo.query.filter(BankSideInfo.state == 'waitApprove').all()

                # 查询还没有正式抵押的一手房贷款业务
                contract_ids = db.session.execute(
                    "select DISTINCT contract_id from tb_bank_side_extend e where e.id not in (select extend_id from tb_house_confirm)"
                ).fetchall()
                contract_ids = [c[0] for c in contract_ids]

                data1 = BankSideInfo.query.filter(
                    and_(
                        BankSideInfo.state == 'confirmed',
                        BankSideInfo.id.in_(contract_ids)
                    )
                ).all()
                data += data1
                data = [model_dict_clear(item.__dict__) for item in data]
            if data is not None and len(data) > 0:
                # 执行查询
                for item in data:
                    if not self.running.isSet():
                        break
                    self.process(item)
            # 每天执行一次
            logger.info('程序：%s, 结束时间：%s， UUID: %s', self.__job_name__, datetime.now().isoformat(), uid)
            # 半分钟执行一次
            time.sleep(5 * 60)
        except Exception as e:
            logger.error("执行任务失败: %s", traceback.format_exc())
            if e.args[0] == '403':
                self.cookies.clear()
                HouseRequest.cookie_dict.clear()
                # 当错误为回话失效时，清空所有的cookie, 等待下次执行
                return
            raise e
